package com.yueyang.sojourn.server.service.sojourn.order;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yueyang.sojourn.server.common.baymax.web.result.JAssert;
import com.yueyang.sojourn.server.model.enums.*;
import com.yueyang.sojourn.server.model.po.*;
import com.yueyang.sojourn.server.service.share.ShareDataService;
import com.yueyang.sojourn.server.service.sojourn.merch.inventory.MerchInventoryService;
import com.yueyang.sojourn.server.service.sojourn.share.SojournShareService;
import com.yueyang.sojourn.server.service.sojourn.tourist.SojournTouristService;
import com.yueyang.sojourn.server.service.sojourn.transaction.SojournTransactionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 订单服务
 * @author andy.yang
 * @version v1
 * @summary
 * @Copyright (c) 2019, yueyang Group All Rights Reserved.
 * @since 2020/3/17
 */
@Service
@Slf4j
public class SojournOrderService {
    @Resource
    SojournOrderMapper sojournOrderMapper;
    @Autowired
    SojournOrderTouristService orderTouristService;
    @Autowired
    SojournTouristService touristService;
    @Autowired
    SojournOrderEventService orderEventService;
    @Autowired
    SojournShareService shareService;
    @Autowired
    SojournTransactionService transactionService;
    @Autowired
    private MerchInventoryService merchInventoryService;
    @Autowired
    private ShareDataService shareDataService;

    /**
     * 创建订单，同时创建对应的游客快照
     * @param order
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long add(SojournOrder order, List<Long> touristIds){
        //创建订单
        sojournOrderMapper.insert(order);
        //创建商品类型订单的附加数据 --游客
        if(touristIds != null && !touristIds.isEmpty()) {
            List<SojournTourist> tourists = touristService.findByIds(touristIds);
            List<SojournOrderTourist> orderTourists = new ArrayList<>();
            tourists.stream().forEach((tourist) -> {
                SojournOrderTourist orderTourist = new SojournOrderTourist();
                BeanUtils.copyProperties(tourist, orderTourist);
                orderTourist.setId(null);
                orderTourist.setOrderId(order.getId());
                orderTourist.setTouristId(tourist.getId());
                orderTourist.setCreator(order.getCreator());
                orderTourist.setStatus(StatusEnum.VALID.getCode());
                orderTourists.add(orderTourist);
            });
            orderTouristService.addBatch(orderTourists);
        }
        //记录事件
        orderEventService.addAndReturn(order.getId(),OrderEventTypeEnum.TO_BE_PAY,order.getCreator());
        return order.getId();
    }

    /**
     * 支付成功更新
     * @param id
     * @param updator
     * @return
     */
    public int updatePaid(Long id,Long updator){
        SojournOrder order = this.findById(id);
        JAssert.pass(order != null, "订单不存在,id=" + id);
        int rs = sojournOrderMapper.updatePaid(id, OrderStatusEnum.TO_BE_TRIP.getCode(), updator);
        orderEventService.addAndReturn(id, OrderEventTypeEnum.TO_BE_TRIP, updator);
        return rs;
    }

    /**
     * 支付即成交：针对vip--即要更新成交状态和时间，同时又更新支付时间
     * @param id
     * @param updator
     * @return
     */
    @Transactional
    public int updatePaidAndDealed(Long id,Long updator){
        //更新为已成交
        int rs = sojournOrderMapper.updatePaidAndDealed(id, OrderStatusEnum.DEALED.getCode(),updator);
        //记录日志
        orderEventService.addAndReturn(id,OrderEventTypeEnum.DEALED,updator);
        //不分账
        shareDataService.dealed(id, "成交了订单");
        return rs;
        //日志 todo
    }
    /**
     * 成交成功更新
     * @param id
     * @param updator
     * @return
     */
    @Transactional
    public int updateDealed(Long id,Long updator){
        SojournOrder order = findById(id);
        //更新为已成交
        int rs = sojournOrderMapper.updateDealed(id, OrderStatusEnum.DEALED.getCode(),updator);
        //记录日志
        orderEventService.addAndReturn(id,OrderEventTypeEnum.DEALED,updator);
        if(OrderTypeEnum.MERCH.getCode() == order.getType()) {
            //分账
            shareService.add(id, updator);
        }
        shareDataService.dealed(id, "成交了订单");
        return rs;
        //日志 todo
    }

    /**
     * 关闭成功时更新
     * @param id
     * @param transactionId
     * @param updator
     * @return
     */
    @Transactional
    public int updateClosedAndTransClosed(Long id,Long transactionId,Long updator){
        int rs = sojournOrderMapper.updateClosed(id, OrderStatusEnum.CLOSED.getCode(),updator);
        if(transactionId != null) {
            SojournTransaction transaction = transactionService.findById(transactionId);
            if (transaction != null && PayConstants.TransactionStatusEnum.PAYING.getCode() == transaction.getStatus()) {
                transaction.setStatus(PayConstants.TransactionStatusEnum.CLOSED_EXPIRE.getCode());
                transactionService.update(transaction);
            }
        }
        orderEventService.addAndReturn(id,OrderEventTypeEnum.CLOSED,updator);
        return rs;
    }

    /**
     * 退款成功时更新
     * @param id
     * @param updator
     * @return
     */
    @Transactional
    public int updateRefunded(Long id,Long updator){
        int rs = sojournOrderMapper.updateRefunded(id, OrderStatusEnum.REFUNDED.getCode(),updator);
        orderEventService.addAndReturn(id,OrderEventTypeEnum.REFUNDED,updator);
        return rs;
    }



    /**
     * 更新订单短信状态
     * @param id
     * @param msgStatus
     * @param updator
     * @return
     */
    public int updateMsgStatus(Long id,int msgStatus,Long updator){
        return sojournOrderMapper.updateMsgStatus(id,msgStatus,updator);
    }

    /**
     * 搜索
     * @param userId      所属用户id
     * @param status      订单状态{@link ShelfStatusEnum#values()}
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return
     * @author Andy.yang
     * @summary 订单分页查询
     * @version v1
     * @since 2020-02-19
     */
    public PageInfo<SojournOrder> findPage(Long userId, String keyword, Date createStartTime, Date createEndTime,
                                           Integer status, Integer type, int pageNo, int pageSize) {
        PageInfo<SojournOrder> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournOrderMapper.findBy(userId,keyword,createStartTime,createEndTime,status,type));
        return pageInfo;
    }

    /**
     * 查询未支付，且将要过期的订单
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return
     * @author Andy.yang
     * @summary 订单分页查询
     * @version v1
     * @since 2020-02-19
     */
    public PageInfo<SojournOrder> findWillExpireToPayPage(int pageNo, int pageSize) {
        PageInfo<SojournOrder> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournOrderMapper.findWillExpireToPay());
        return pageInfo;
    }

    /**
     * 查询未支付，且将要在指定时间(分钟)过期的订单
     * @param pageNo      页码
     * @param pageSize    页大小
     * @return
     * @author Andy.yang
     * @summary 订单分页查询
     * @version v1
     * @since 2020-02-19
     */
    public PageInfo<SojournOrder> findWillExpireToPayInTimePage(int minutes ,int pageNo, int pageSize) {
        PageInfo<SojournOrder> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournOrderMapper.findWillExpireToPayInTime(minutes));
        return pageInfo;
    }

    /**
     * 获取分销员的分销被下单列表
     * @param userId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<SojournOrder> findMyShareOrderList(Long userId, int pageNo, int pageSize) {
        PageInfo<SojournOrder> pageInfo = PageHelper.startPage(pageNo, pageSize)
                .doSelectPageInfo(() -> sojournOrderMapper.findMyShareOrderList(userId));
        return pageInfo;
    }

    /**
     * @param orderId      所属订单id
     * @return
     * @author Andy.yang
     * @summary 订单分页查询
     * @version v1
     * @since 2020-02-19
     */
    public SojournOrder findById(Long orderId) {
        return sojournOrderMapper.selectByPrimaryKey(orderId);
    }

    /**
     * @param sn      所属订单号
     * @return
     * @author Andy.yang
     * @summary
     * @version v1
     * @since 2020-02-19
     */
    public SojournOrder findByOrderSn(String sn) {
        return sojournOrderMapper.findByOrderSn(sn);
    }
}
